import {Component} from '@angular/core';
import {ApesField} from './apes-field';
import {
  backField,
  getO,
  getText,
  getValueUsingField,
  missing,
  replaceAll,
  type,
} from '../../../../utils/utils';
import {ApiService} from '@core/services/http/api.service';
import {Events} from '@core/services/events/Events';
import {ExpressionService} from '@core/services/expression/ExpressionService';
import {SubjectService} from '@core/services/events/subject.service';
import { Subject } from 'rxjs/internal/Subject';
import { catchError, debounceTime, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
import { of } from 'rxjs/internal/observable/of';
import { SearchService } from '@core/services/search.service';
import { toBoolean, toNumber } from '@shared/apes/core/util/convert';

@Component({
  selector: 'formly-field-operate-select',
  template: `
    <div apes-row>
      <div apes-col apesMd="24">
        <ng-select [items]="itemsData"
                   bindLabel="name"
                   [hideSelected]="true"
                   [optionWidth]="width"
                   [disabled]="to.disabled"
                   [placeholder]="to.placeholder"
                   [multiple]="multiple"
                   [formlyAttributes]="field"
                   [formControl]="formControl"
                   [virtualScroll]="true"
                   [loading]="contractLoading"
                   [typeahead]="contractinput$"
                   [searchBtn]="_searchBtn"
                   [searchable]="_ShowSearch"
                   [iconType]="iconType"
                   (searchBtnFn)="onSearch()"
                   (change)="backData()"
                   (scrollToEnd)="fetchMore()">
          <!-- 表头部分 -->
          <ng-template ng-label-tmp let-item="item" let-clear="clear">
            <span class="ng-value-label">{{formatter(item, getValueFormatter())}}</span>
            <span class="ng-value-icon right" (click)="clear(item)" aria-hidden="true">×</span>
          </ng-template>
          <ng-template ng-option-tmp let-item="item">
            <span class="ng-value-label">{{formatter(item, getDownFormatter())}}</span>
          </ng-template>

        </ng-select>
      </div>
    </div>
  `,
})
export class FormlyFieldSelectOperateGrid extends ApesField {
  apesConfig: any;
  searchFormId: string;
  iconType: string; // 按钮展示图标
  searchSelectApi: string;
  _ShowSearch = true;
  _searchBtn = false;
  contractLoading = false;
  itemsData: any[] = [];
  contractinput$ = new Subject<string>();
  multiple = false;
  width = 0;
  size = 20;
  private _current = 0;
  private _pages = 0;
  private _searchText = '';
  private _domain;
  private _transfer: boolean = false;

  constructor(protected apiService: ApiService, protected events: Events, protected expressionService: ExpressionService,
              protected subject: SubjectService, protected searchService: SearchService) {
    super(apiService, events, expressionService, subject);
    this.loadContract();
  }

  ngOnInit() {
    this._searchBtn = true;
    this.apesConfig = this.extend(this.to);
    this.width = this.to.width;
    this.searchFormId = this.to.searchFormId;
    this.searchSelectApi = this.to.api;
    this.iconType = this.to.iconType ? this.to.iconType : 'search';
    this.multiple = this.to.multiple === 'true' || false;
    this.size = this.to.size ? toNumber(this.to.size) : 20;
    if (this.to['domain']) {
      this.to.domain = replaceAll(this.to.domain, '\'', '');
      this._domain = JSON.parse(this.to.domain);
    }

    // 设置下拉选项
    if (this.to['items']) {
      this.itemsData = getO(this.to['items']);
      this._ShowSearch = false;
    }
    if (this.to['dialogType'] === 'transfer') {
      this._transfer = true;
      this.multiple = true;
      this._ShowSearch = false;
      this.apesConfig.init = true;
    }

    if(!this.to.table) console.error("请输入对应的table名");

    // 监听数据的改变
    this.subject.subscribe(this.formState, this.to.table, (data) => {
      if( data.event === "selectionChanged" ) {
        this.formState.model[this.to.table+"Selected"] = data.data;
      }
    });

  }
  ngAfterViewInit(): void {
    // 增加 init xml 选项，表示不搜索下拉， 默认查询api作为下拉选项
    if (this.apesConfig['init'] && this.apesConfig['api']) {
      this.getItemData();
      // this._ShowSearch = false;
    }
    if (this._ShowSearch) {
      this.loadContract();
    }
  }
  protected extend(data: any) {
    const result = {};
    for (const key in data) {
      const value = data[key];
      result[key] = value;
    }
    return result;
  }
  backData() {
    const context = this.to.context || {};
    backField(this, context);
  }


  private loadContract() {
    this.contractinput$.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      tap(() => this.contractLoading = true),
      switchMap((term) => {
        if (missing(term)) {
          this.contractLoading = false;
          return of([]);
        }
        if ( this._searchText === term) return of([]);
        this._current = 0;
        this._searchText = term;
        const data = this.getApiParams();
        return this.apiService.post(this.searchSelectApi, data).pipe(
          map((res) => {
              this.itemsData = [];
              this._searchText = term;
              this.itemsData = this.itemsData.concat(res.content);
              this._current = res.page + 1;
              this._pages = res.pages;
              return res.content;
            }
          ),
          catchError(() => of([])), // empty list on error
          tap(() => this.contractLoading = false)
        ); })
    ).subscribe();
  }


  fetchMore() {
    this.contractLoading = true;
    // using timeout here to simulate backend API delay
    if (this._current === this._pages || this._searchText === '') {
      this.contractLoading = false;
      return;
    }
    this.getItemData();
  }
  getItemData() {
    const data = this.getApiParams();
    this.apiService.post(this.searchSelectApi, data).subscribe(item => {
      this.contractLoading = false;
      if (item.page === 0) {
        this.itemsData = [];
      }
      this.itemsData = this.itemsData.concat(item.content);
      this._current = item.page + 1;
      this._pages = item.pages;
    });
  }

  /*
  * 写入事件
  * */
  onSearch() {
    let callback = this.to.events[0].callback;
    return this.expressionService.evaluate(callback, {
      context: this.formState,
      form: this.form,
      field: this.field,
      model: this.formState.model,
      value: {}
    }, true);
  }


  // 获取不重复项数组
  private getUniqueArray(array: Array<any>, id: string): Array<any> {
    array = Array.from(new Set(array));
    if ( typeof array[0] === 'object' ) {
      const res = new Map();
      array = array.filter((a) => !res.has(a[id]) && res.set(a[id], 1));
    }
    return array;
  }


  getValueFormatter(): string {
    return this.to.valueFormatter || 'value.name';
  }
  getDownFormatter(): string {
    return this.to.downFormatter || '\'[ \' + value.id + \' ]\' + \' \' + value.name';
  }
  getApiParams() {
    const data = {key: this._searchText, page: this._current, size: this.size};
    if (this._domain) {
      const group = this.fillField(this._domain);
      data['group'] = group;
    }
    return data;
  }

  // 对传入的域进行处理
  private fillField(domain: any, searchFlag: Boolean = false) {
    let result;
    if (type(domain) === 'object') {
      result = {};
    } else {
      result = [];
    }
    for (const key in domain) {
      let value = domain[key];
      const t = type(value);
      if (t === 'object') {
        value = this.fillField(value, searchFlag);
      } else if (t === 'array') {
        value = [...this.fillField(value, searchFlag)];
      } else {
        if (t === 'string') {
          const text = getText(value);
          if (text) {
            if (text === 'value') {
              if (searchFlag)  return;
              value = this._searchText;
            } else {
              value = getValueUsingField(this.formState, text, true);
            }
          }
        }
      }

      let val = value;
      if ( type(value) === 'array' ) {
        if (type(val) === 'array') {
          // 对解析出的数据做出筛选
          val = val.filter((elem) =>  elem !== undefined);
        }
        value = val;
      } else if ( type(value) === 'object' && val.filters ) {
        if ( val.filters.length === 0 ) {
          if ( val.groups.length === 0 ) {
            val = [];
          } else {
            val.filters = val.groups;
            val.groups = [];
          }
        }
      }

      if ( key === 'groups' && val[0] && val[0].length === 0) {
        result[key] = [];
      } else {
        result[key] = val;
      }
    }
    console.log(result);
    return result;
  }

  formatter(value: any, expression: string) {
    return this.expressionService.evaluate(expression, {
      context: this.formState,
      model: this.formState.model,
      value: value
    });
  }

}
